#ifndef MPIOCONTEXTTEST_H
#define MPIOCONTEXTTEST_H

#include <string>
#include <thread>
#include <iostream>

#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include "mpTestConfig.h"

class Printer
{
public:
    Printer(boost::asio::io_context& io)
        :
          m_timer1(io, boost::asio::chrono::seconds(1)),
          m_timer2(io, boost::asio::chrono::seconds(1)),
          count_(0)
    {
        m_timer1.async_wait(boost::bind(&Printer::print1, this));
        m_timer2.async_wait(boost::bind(&Printer::print2, this));
    }
    ~Printer()
    {
        std::cout << "Final count is " << count_ << std::endl;
    }
protected:
    void print1()
    {
        if (count_ < 10)
        {
            std::cout << "(print1)thread id :" << std::this_thread::get_id() << " count: "  << count_ << std::endl;

            ++count_;
            m_timer1.expires_at(m_timer1.expiry() + boost::asio::chrono::seconds(1));
            m_timer1.async_wait(boost::bind(boost::bind(&Printer::print1, this)));
        }
    }

    void print2()
    {
        if (count_ < 10)
        {
            std::cout << "(print2)thread id :" << std::this_thread::get_id() << " count: "  << count_ << std::endl;

            ++count_;
            m_timer2.expires_at(m_timer2.expiry() + boost::asio::chrono::seconds(1));
            m_timer2.async_wait(boost::bind(boost::bind(&Printer::print2, this)));
        }
    }
private:
    boost::asio::steady_timer m_timer1;
    boost::asio::steady_timer m_timer2;
    int count_;
};

class PrinterStrand
{
public:
    PrinterStrand(boost::asio::io_context& io)
        : m_strand(io),
          m_timer1(io, boost::asio::chrono::seconds(1)),
          m_timer2(io, boost::asio::chrono::seconds(1)),
          count_(0)
    {
        //        m_timer1.async_wait(boost::bind(&Printer::print1, this));
        //        m_timer2.async_wait(boost::bind(&Printer::print2, this));

        m_timer1.async_wait(boost::asio::bind_executor(m_strand, boost::bind(&PrinterStrand::print1, this)));
        m_timer2.async_wait(boost::asio::bind_executor(m_strand, boost::bind(&PrinterStrand::print2, this)));
    }
    ~PrinterStrand()
    {
        std::cout << "Final count is " << count_ << std::endl;
    }
protected:
    void print1()
    {
        if (count_ < 10)
        {
            {
                std::lock_guard<std::mutex> lock{ _mutex };

                std::cout << "(print1)thread id :" << std::this_thread::get_id() << " count: "  << count_ << std::endl;
                ++count_;
            }
            m_timer1.expires_at(m_timer1.expiry() + boost::asio::chrono::seconds(1));
            m_timer1.async_wait(boost::asio::bind_executor(m_strand, boost::bind(&PrinterStrand::print1, this)));
        }
    }

    void print2()
    {
        if (count_ < 10)
        {
            {
                std::lock_guard<std::mutex> lock{ _mutex };

                std::cout << "(print2)thread id :" << std::this_thread::get_id() << " count: "  << count_ << std::endl;
                ++count_;
            }

            m_timer2.expires_at(m_timer2.expiry() + boost::asio::chrono::seconds(1));
            m_timer2.async_wait(boost::asio::bind_executor(m_strand, boost::bind(&PrinterStrand::print2, this)));
        }
    }
private:
    boost::asio::io_context::strand m_strand;
    boost::asio::steady_timer m_timer1;
    boost::asio::steady_timer m_timer2;
    std::mutex _mutex;
    int count_;
};

//在多线程程序中同步处理器
//class PrintNew
//{
//public:
//    PrintNew(boost::asio::io_context& io)
//        : strand_(boost::asio::make_strand(io))
//        , timer1_(io, boost::asio::chrono::seconds(1))
//        , timer2_(io, boost::asio::chrono::seconds(1))
//        , count_(0)
//    {
//        timer1_.async_wait(boost::asio::bind_executor(strand_, boost::bind(&PrintNew::print1, this)));
//        timer2_.async_wait(boost::asio::bind_executor(strand_, boost::bind(&PrintNew::print2, this)));
//    }
//    ~PrintNew()
//    {
//        std::cout << "Final count is " << count_ << std::endl;
//    }
//protected:
//    void print1()
//    {
//        if (count_ < 10)
//        {
//            std::cout << "Timer 1: " << count_ << std::endl;
//            ++count_;
//            timer1_.expires_at(timer1_.expiry() + boost::asio::chrono::seconds(1));
//            timer1_.async_wait(boost::asio::bind_executor(strand_, boost::bind(&PrintNew::print1, this)));
//        }
//    }
//    void print2()
//    {
//        if (count_ < 10)
//        {
//            std::cout << "Timer 2: " << count_ << std::endl;
//            ++count_;
//            timer2_.expires_at(timer2_.expiry() + boost::asio::chrono::seconds(1));
//            timer2_.async_wait(boost::asio::bind_executor(strand_, boost::bind(&PrintNew::print2, this)));
//        }
//    }
//private:
//    boost::asio::strand<boost::asio::io_context::executor_type> strand_;
//    boost::asio::steady_timer timer1_;
//    boost::asio::steady_timer timer2_;
//    int count_;
//};



#endif // MPIOCONTEXTTEST_H
